package top.z.orm.handle.osql.core;

import top.z.orm.core.osql.*;
import top.z.orm.core.osql.dialect.DbFeature;
import top.z.orm.core.osql.exception.NoConfigException;
import top.z.orm.handle.osql.dialect.LimitOffsetPaging;
import top.z.orm.handle.osql.dialect.mysql.MySqlFeature;
import top.z.orm.handle.osql.dialect.oracle.OracleFeature;
import top.z.orm.handle.osql.dialect.sqlserver.SqlServerFeature;
import top.z.orm.handle.osql.name.OriginalName;
import top.z.orm.handle.osql.name.UnderScoreAndCamelName;

public class HoneyFactory {

    private Suid          suid;
    private SuidRich      suidRich;
    private BeeSql        beeSql;
    private ObjToSQL      objToSQL;
    private ObjToSQLRich  objToSQLRich;
    private PreparedSql   preparedSql;
    private CallableSql   callableSql;
    private DbFeature     dbFeature;
    private NameTranslate nameTranslate;
    private Cache         cache;
    private MoreObjToSQL  moreObjToSQL;
    private MoreTable     moreTable;
    private MapSql        mapSql;
    private MapSuid       mapSuid;
    //-------------------------------------------------------------
    //---------------------------- set ----------------------------
    //-------------------------------------------------------------

    public HoneyFactory setSuid(Suid suid) {
        this.suid = suid;
        return this;
    }

    public HoneyFactory setSuidRich(SuidRich suidRich) {
        this.suidRich = suidRich;
        return this;
    }

    public HoneyFactory setBeeSql(BeeSql beeSql) {
        this.beeSql = beeSql;
        return this;
    }

    public HoneyFactory setObjToSQL(ObjToSQL objToSQL) {
        this.objToSQL = objToSQL;
        return this;
    }

    public HoneyFactory setObjToSQLRich(ObjToSQLRich objToSQLRich) {
        this.objToSQLRich = objToSQLRich;
        return this;
    }

    public HoneyFactory setPreparedSql(PreparedSql preparedSql) {
        this.preparedSql = preparedSql;
        return this;
    }

    public HoneyFactory setCallableSql(CallableSql callableSql) {
        this.callableSql = callableSql;
        return this;
    }

    public HoneyFactory setDbFeature(DbFeature dbFeature) {
        this.dbFeature = dbFeature;
        return this;
    }

    public HoneyFactory setNameTranslate(NameTranslate nameTranslate) {
        this.nameTranslate = nameTranslate;
        return this;
    }

    public HoneyFactory setCache(Cache cache) {
        this.cache = cache;
        return this;
    }

    public HoneyFactory setMoreObjToSQL(MoreObjToSQL moreObjToSQL) {
        this.moreObjToSQL = moreObjToSQL;
        return this;
    }

    public HoneyFactory setMoreTable(MoreTable moreTable) {
        this.moreTable = moreTable;
        return this;
    }

    public HoneyFactory setMapSql(MapSql mapSql) {
        this.mapSql = mapSql;
        return this;
    }

    public HoneyFactory setMapSuid(MapSuid mapSuid) {
        this.mapSuid = mapSuid;
        return this;
    }

    //-------------------------------------------------------------
    //---------------------------- set ----------------------------
    //-------------------------------------------------------------
    public Suid getSuid() {
        if (suid == null) {
            return new ObjSQL();
        }
        return suid;
    }

    public SuidRich getSuidRich() {
        if (suidRich == null) {
            return new ObjSQLRich();
        }
        return suidRich;
    }

    public MoreTable getMoreTable() {
        if (moreTable == null) {
            return new MoreObjSQL();
        }
        return moreTable;
    }

    public BeeSql getBeeSql() {
        if (this.beeSql == null) {
            return new SqlLib();
        }
        return beeSql;
    }

    public ObjToSQL getObjToSQL() {
        if (objToSQL == null) {
            return new ObjectToSQL();
        }
        return objToSQL;
    }

    public ObjToSQLRich getObjToSQLRich() {
        if (objToSQLRich == null) {
            return new ObjectToSQLRich();
        }
        return objToSQLRich;
    }

    public MoreObjToSQL getMoreObjToSQL() {
        if (moreObjToSQL == null) {
            return new MoreObjectToSQL();
        }
        return moreObjToSQL;
    }

    public PreparedSql getPreparedSql() {
        if (preparedSql == null) {
            return new PreparedSqlLib();
        }
        return preparedSql;
    }

    public CallableSql getCallableSql() {
        if (callableSql == null) {
            return new CallableSqlLib();
        }
        return callableSql;
    }

    public MapSql getMapSql() {
        if (mapSql == null) {
            return new MapSqlImpl();
        }
        return mapSql;
    }

    public MapSuid getMapSuid() {
        if (mapSuid == null) {
            return new MapSuidImpl();
        }
        return mapSuid;
    }

    private DbFeature _getDbDialect() {
        if (DatabaseConst.MYSQL.equalsIgnoreCase((HoneyContext.getDbDialect())) || DatabaseConst.MariaDB.equalsIgnoreCase((HoneyContext.getDbDialect()))) {
            return new MySqlFeature();
        } else if (DatabaseConst.ORACLE.equalsIgnoreCase((HoneyContext.getDbDialect()))) {
            return new OracleFeature();
        } else if (DatabaseConst.SQLSERVER.equalsIgnoreCase((HoneyContext.getDbDialect()))) {
            return new SqlServerFeature();
        } else if (_isLimitOffsetDB()) {
            return new LimitOffsetPaging();
        } else {
            // 要用 setDbFeature(DbFeature dbFeature) 设置自定义的实现类
            // todo 也有可能是没开DB服务
            throw new NoConfigException("Error: Do not set the DbFeature implements class or do not set the database name");
        }
    }

    private boolean _isLimitOffsetDB() {
        String dbType = HoneyContext.getDbDialect();
        return DatabaseConst.H2.equalsIgnoreCase(dbType) || DatabaseConst.SQLite.equalsIgnoreCase(dbType) || DatabaseConst.PostgreSQL.equalsIgnoreCase(dbType);
    }

    public DbFeature getDbFeature() {
        if (dbFeature != null) {
            return dbFeature;
        } else {
            return _getDbDialect();
        }
    }

    NameTranslate getNameTranslate() {
        if (nameTranslate == null) {
            int translateType = HoneyConfig.getHoneyConfig().getNamingTranslateType();
            if (translateType == 1) {
                nameTranslate = new UnderScoreAndCamelName();
            } else if (translateType == 2) {
                nameTranslate = new UpperCaseUnderScoreAndCamelName();
            } else if (translateType == 3) {
                nameTranslate = new OriginalName();
            }
            return nameTranslate;
        } else {
            return nameTranslate;
        }
    }

    public Cache getCache() {
        if (cache == null) {
            Boolean enableCache = CoreConfig.getEnableCache();
            return enableCache ? new DefaultCache() : new NoCache();
        } else {
            return cache;
        }
    }
}